/**
 *
 * \file CColor.cpp
 * \brief This file contains the CColor class implementation.
 * \author Vladimir Klubkov (aka marked)
 *
 * Last changes date:
 * \date 15.03.2011
 *
 * Copyright 2011 Vladimir Klubkov <marked-one@yandex.ru>
 *
 * This file is part of OOXlib.
 *
 * OOXLib is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * OOXlib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with OOXlib; if not, you can try to find  it here:
 * http://www.gnu.org/licenses/gpl.txt
 * or write to the Free Software Foundation, Inc., 59 Temple Place,
 * Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "../include/CColor.h"

namespace OOXlib {

/**
 * Constructor. Calls the base-class constructor.
 * \param File Source code file name.
 * \param iLine Source code line.
 * \param Function Function name.
 */
CColor::CXAllocColorException::CXAllocColorException(const ::std::string &File, const int iLine, const ::std::string &Function)
: CException(File, iLine, Function, "Can't create the CColor object. The XAllocColor function failed.") {}
/**
 * Constructor. Creates the default color.
 * \param pXServerConnection A pointer to the CXServerConnection object.
 * \param pScreen A pointer to the CScreen object.
 */
CColor::CColor(const CXServerConnection *pXServerConnection, const CScreen *pScreen)
: m_pXServerConnection(pXServerConnection) {
    if(NULL == m_pXServerConnection) {
        OOXLib_THROW(CNULLPtrConnectionException);
    }
    if(NULL == pScreen) {
        OOXLib_THROW(CNULLPtrScreenException);
    }
    // Create the colormap.
    m_Colormap = ::XDefaultColormap(m_pXServerConnection->Get(), pScreen->Get());
    // Create the color.
    m_Color.red     = 0;
    m_Color.green   = 0;
	m_Color.blue    = 0;
	m_Color.flags   = DoRed | DoGreen | DoBlue;
	// Allocate the color.
	// XAllocColor can generate a BadColor error.
    if(0 == ::XAllocColor(m_pXServerConnection->Get(), m_Colormap, &m_Color)) {
        OOXLib_THROW(CXAllocColorException);
    }
}
/**
 * Constructor. Creates the color.
 * \param pXServerConnection A pointer to the CXServerConnection object.
 * \param pScreen A pointer to the CScreen object.
 * \param iRed Input parameter, red color, 0 to 255.
 * \param iGreen Input parameter, green color, 0 to 255.
 * \param iBlue Input parameter, blue color, 0 to 255.
 */
CColor::CColor(const CXServerConnection *pXServerConnection, const CScreen *pScreen, unsigned char iRed, unsigned char iGreen, unsigned char iBlue)
: m_pXServerConnection(pXServerConnection) {
    if(NULL == m_pXServerConnection) {
        OOXLib_THROW(CNULLPtrConnectionException);
    }
    if(NULL == pScreen) {
        OOXLib_THROW(CNULLPtrScreenException);
    }
    // Create the colormap.
    m_Colormap = ::XDefaultColormap(m_pXServerConnection->Get(), pScreen->Get());
    // Create the color.
    // Magic constant - 257 - is 65535/255. We convert here every value from 256 to 65536 colors.
    m_Color.red     = static_cast<short>(iRed) * 257;
    m_Color.green   = static_cast<short>(iGreen) * 257;
	m_Color.blue    = static_cast<short>(iBlue) * 257;
	m_Color.flags   = DoRed | DoGreen | DoBlue;
	// Allocate color.
    // XAllocColor can generate a BadColor error.
    if(0 == ::XAllocColor(m_pXServerConnection->Get(), m_Colormap, &m_Color)) {
        OOXLib_THROW(CXAllocColorException);
    }
}
/**
 * Destructor. Frees the allocated color.
 */
CColor::~CColor() {
    // We need at least one pixel.
    int pixelCount = 1;
    unsigned long planes = 0;
    // Create array of pixels.
    unsigned long pixels[pixelCount + 1];
    // Become the color pixel into the array.
	pixels[0] = GetPixel();
	// And yes! Now we are able to free the color.
	// XFreeColors can generate BadAccess , BadColor , and BadValue errors.
    ::XFreeColors(m_pXServerConnection->Get(), m_Colormap, pixels, pixelCount, planes);
}
/**
 * Returns the color pixel value.
 * \return Color pixel value.
 */
unsigned long CColor::GetPixel() const {
    return m_Color.pixel;
}

} // OOXlib
